#ifndef __MSGQUEUE_CPP__
#define __MSGQUEUE_CPP__

#include "env.h"
#include "section.h"
#include "bytearrays.h"
#include "output.h"
#include "msghandle.h"
#include "msgqueue.h"

namespace WServer {

namespace MsgQueue {

std::list<MsgHandle::wmsgdata*> clientmsglist;
std::vector<std::deque<MsgHandle::wmsgdata*> > servermsglist;

void wserInitMsgQueue(int mindex)
{
	int i;
	char* p = new char[sizeof(struct GData::wserSocketData)];
	memset(p, 0, sizeof(struct GData::wserSocketData));
	for (i = 0;i < GData::servermsglength;i++) {
		std::deque<MsgHandle::wmsgdata*> lmsg;
		servermsglist.push_back(lmsg);
	}

	for (i = 0;i < GData::maxconn;i++) {
		__rwsize = write(GData::fsmem, p, sizeof(struct GData::wserSocketData));
	}
	GData::clientlist = (struct GData::wserSocketData*)mmap(NULL, sizeof(struct GData::wserSocketData)*GData::maxconn, PROT_READ|PROT_WRITE, MAP_SHARED, GData::fsmem, 0);
	delete[] p;p = NULL;
}

void wserUninitMsgQueue()
{
}

void PushStream(int index, void* p, int packlen, int from, int to)
{
	int ltlen = packlen;
	char* cct = (char*)p;

	while (1) {
		if (ltlen <= 0) break;
		if (clientmsglist.size() == 0 || clientmsglist.back()->bend) {
			if (ltlen < 8) return;
			struct MsgHandle::wmsgdata* pmsg = new struct MsgHandle::wmsgdata();
			int ylen = *(int*)cct;
			if (ylen <= ltlen) {
				pmsg->packetstream(index, from, to, ylen, cct);
				cct += ylen;
				ltlen -= ylen;
			}
			else {
				pmsg->packetstream(index, from, to, ltlen, cct);
				cct += ltlen;
				ltlen -= ltlen;
			}
			clientmsglist.push_back(pmsg);
		}
		else {
			int lplen = clientmsglist.back()->len-clientmsglist.back()->current;
			if (lplen > ltlen) {
				memcpy((char*)clientmsglist.back()->param+clientmsglist.back()->current, (char*)cct, ltlen);
				clientmsglist.back()->current += ltlen;
				break;
			}
			else {
				memcpy((char*)clientmsglist.back()->param+clientmsglist.back()->current, (char*)cct, lplen);
				ltlen -= lplen;
				clientmsglist.back()->current = 0;
				clientmsglist.back()->bend = true;
			}
		}
	}

	while (clientmsglist.size() > 0) {
		if (clientmsglist.front()->bend) {
			MsgHandle::SendMessage2WMain(clientmsglist.front()->type, clientmsglist.front()->clientindex, clientmsglist.front()->len, clientmsglist.front()->param);
			delete clientmsglist.front();
			clientmsglist.pop_front();
		}
		else
			break;
	}
}

boost::tuple<int, void*, int> PopStream(int inc)
{
	int len = 0;
	int current;

	if (servermsglist[inc].size() == 0) {
		return boost::make_tuple<int, void*, int>(0, NULL, len);
	}

	if (servermsglist[inc].front()->bend) {
		delete servermsglist[inc].front();
		servermsglist[inc].pop_front();
	}
	if (servermsglist[inc].size() == 0) {
		return boost::make_tuple<int, void*, int>(0, NULL, 0);
	}
	MsgHandle::wmsgdata* pmsg = servermsglist[inc].front();
	char* p = (char*)pmsg->param+pmsg->current;
	current = pmsg->current;
	if (pmsg->current+MEMORYPOOLSIZE >= pmsg->len+12) {
		len = pmsg->len+12-pmsg->current;
		pmsg->current += len;
		pmsg->bend = true;
	}
	else {
		len = MEMORYPOOLSIZE;
		pmsg->current += len;
	}
	return boost::make_tuple<int, void*, int>(pmsg->clientindex, (char*)pmsg->param+current, len);
}

MsgHandle::wmsgdata* PopMessage(int inc)
{
	int current, len = 0;

	if (servermsglist[inc].size() == 0) {
		return 0;
	}
	if (servermsglist[inc].front()->bend) {
		delete servermsglist[inc].front();
		servermsglist[inc].pop_front();
	}
	if (servermsglist[inc].size() == 0) {
		return 0;
	}
	MsgHandle::wmsgdata* pmsg = servermsglist[inc].front();
	pmsg->bend = true;
	return pmsg;
}

} //namespace MsgQueue

} //namespace WServer

#endif //__MSGQUEUE_CPP__
